package cn.iocoder.yudao.module.ems.service.outbound;

import cn.iocoder.yudao.module.ems.controller.admin.outbound.vo.OutboundInfoCreateReqVO;
import cn.iocoder.yudao.module.ems.controller.admin.outbound.vo.OutboundInfoRespVO;
import cn.iocoder.yudao.module.ems.convert.outbound.OutboundConvert;
import cn.iocoder.yudao.module.ems.convert.outbound.OutboundInfoConvert;
import cn.iocoder.yudao.module.ems.dal.dataobject.spares.SparesDO;
import cn.iocoder.yudao.module.ems.dal.dataobject.outbound.OutboundDO;
import cn.iocoder.yudao.module.ems.dal.dataobject.outbound.OutboundInfoDO;
import cn.iocoder.yudao.module.ems.dal.dataobject.outbound.OutboundDO;
import cn.iocoder.yudao.module.ems.dal.dataobject.outbound.OutboundInfoDO;
import cn.iocoder.yudao.module.ems.dal.mysql.spares.SparesMapper;
import cn.iocoder.yudao.module.ems.dal.mysql.outbound.OutboundInfoMapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import cn.iocoder.yudao.module.ems.controller.admin.outbound.vo.*;
import cn.iocoder.yudao.module.ems.dal.dataobject.outbound.OutboundDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.ems.convert.outbound.OutboundConvert;
import cn.iocoder.yudao.module.ems.dal.mysql.outbound.OutboundMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.ems.enums.ErrorCodeConstants.*;

/**
 * 出库记录 Service 实现类
 *
 * @author dason
 */
@Service
@Validated
public class OutboundServiceImpl implements OutboundService {

    @Resource
    private OutboundMapper outboundMapper;

    @Resource
    private OutboundInfoMapper outboundInfoMapper;
    
    @Resource
    private SparesMapper sparesMapper;

    @Override
    public Long createOutbound(OutboundCreateReqVO createReqVO) {
        // 插入
        OutboundDO outbound = OutboundConvert.INSTANCE.convert(createReqVO);
        outboundMapper.insert(outbound);
        Collection<OutboundInfoCreateReqVO> InfoList = createReqVO.getOutboundInfo();
        for (OutboundInfoCreateReqVO info: InfoList) {
            SparesDO spares = sparesMapper.selectByItemNo(info.getItemNo());
            if (spares == null) {
                throw exception(SPARES_ITEMNO_NOTEXISTS);
            }
            info.setOutboundId(outbound.getId());
            outboundInfoMapper.insert(OutboundInfoConvert.INSTANCE.convert4(info));
            sparesMapper.updateAmountByInfo(spares, info.getNumber());
        }
        // 返回
        return outbound.getId();
    }

    @Override
    public void updateOutbound(OutboundUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateOutboundExists(updateReqVO.getId());
        // 更新
        OutboundDO updateObj = OutboundConvert.INSTANCE.convert(updateReqVO);
        // 入库信息
        Collection<OutboundInfoRespVO> InfoList = updateReqVO.getOutboundInfo();
        for (OutboundInfoRespVO info: InfoList) {
            SparesDO spares = sparesMapper.selectByItemNo(info.getItemNo());
            if (spares == null) {
                throw exception(SPARES_ITEMNO_NOTEXISTS);
            }
            info.setOutboundId(updateReqVO.getId());
            if(info.getId() != null) {
                OutboundInfoDO rawInfo = outboundInfoMapper.selectById(info.getId());
                // 物料编号相等
                if(Objects.equals(info.getItemNo(), rawInfo.getItemNo())) {
                    if(!Objects.equals(info.getNumber(), rawInfo.getNumber())) {
                        sparesMapper.updateAmountByInfo(spares, info.getNumber() - rawInfo.getNumber());
                    }
                    outboundInfoMapper.updateById(OutboundInfoConvert.INSTANCE.convert3(info));
                } else {
                    SparesDO other = sparesMapper.selectByItemNo(rawInfo.getItemNo());
                    sparesMapper.updateAmountByInfo(other, -rawInfo.getNumber());
                    sparesMapper.updateAmountByInfo(spares, info.getNumber());
                }
            } else {
                outboundInfoMapper.insert(OutboundInfoConvert.INSTANCE.convert3(info));
                sparesMapper.updateAmountByInfo(spares, info.getNumber());
            }
        }
        outboundMapper.updateById(updateObj);
    }

    @Override
    public void deleteOutbound(Long id) {
        // 校验存在
        this.validateOutboundExists(id);
        OutboundDO w = outboundMapper.selectById(id);
        List<OutboundInfoDO> infoList = outboundInfoMapper.selectList(id);
        for(OutboundInfoDO info : infoList) {
            SparesDO spares = sparesMapper.selectByItemNo(info.getItemNo());
            sparesMapper.updateAmountByInfo(spares, -info.getNumber());
            outboundInfoMapper.deleteById(info.getId());
        }
        // 删除
        outboundMapper.deleteById(id);
    }

    private void validateOutboundExists(Long id) {
        if (outboundMapper.selectById(id) == null) {
            throw exception(OUTBOUND_NOT_EXISTS);
        }
    }

    @Override
    public OutboundDO getOutbound(Long id) {
        return outboundMapper.selectById(id);
    }

    @Override
    public List<OutboundDO> getOutboundList(Collection<Long> ids) {
        return outboundMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OutboundDO> getOutboundPage(OutboundPageReqVO pageReqVO) {
        return outboundMapper.selectPage(pageReqVO);
    }

    @Override
    public List<OutboundDO> getOutboundList(OutboundExportReqVO exportReqVO) {
        return outboundMapper.selectList(exportReqVO);
    }

}
